package com.jiexin.filter;

import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.jiexin.common.ApplicationContextHelper;
import com.jiexin.common.JsonData;
import com.jiexin.common.RequestHolder;
import com.jiexin.model.SysUser;
import com.jiexin.service.SysCoreService;
import com.jiexin.util.JsonMapper;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author: Jay_Liu
 * @Description:
 * @Date: Created in 9:42 2018/4/29 0029
 * @Modified By:
 */
@Slf4j
public class AclControlFilter implements Filter {

    public static Set<String> exclusionUrlSet = Sets.newConcurrentHashSet();

    public static final String noAuthRedirectUrl = "/sys/user/noAuth.page";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //不拦截的白名单地址信息
        String exclusionUrls = filterConfig.getInitParameter("exclusionUrls");
        List<String> exclusionUrlList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(exclusionUrls);
        //转换成全局Set
        exclusionUrlSet = Sets.newConcurrentHashSet(exclusionUrlList);
        exclusionUrlSet.add(noAuthRedirectUrl);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //请求路径
        String servletPath = request.getServletPath();
        //请求参数集合
        Map parameterMap = request.getParameterMap();
        //白名单路径不进行处理
        if(exclusionUrlSet.contains(servletPath)) {
            filterChain.doFilter(request, response);
            return;
        }
        //当前系统登录用户
        SysUser sysUser = RequestHolder.getCurrentUser();
        if(sysUser == null) {
            log.info("someone visit {} but no login, parameterMap:{}", servletPath, JsonMapper.obj2String(parameterMap));
            noAthu(request, response);
            return;
        }
        //检查用户是否有路径的访问权限
        SysCoreService sysCoreService = ApplicationContextHelper.popBean(SysCoreService.class);
        if(!sysCoreService.hasUrlAcl(servletPath)){
            log.info("{} visit {} but no login, parameterMap:{}", sysUser.getUsername(), servletPath, JsonMapper.obj2String(parameterMap));
            noAthu(request, response);
            return;
        }
        //若无问题放过过滤
        filterChain.doFilter(servletRequest, servletResponse);
        return;
    }

    /**
     * 无权限处理
     * @param request
     * @param response
     */
    private void noAthu(HttpServletRequest request, HttpServletResponse response) throws IOException{
        String servletUrl = request.getServletPath();
        if(servletUrl.endsWith(".json")){
            JsonData noAthuResult = JsonData.fail("无权限访问,如有需要,请联系管理员");
            response.setHeader("Content-Type", "application/json");
            response.getWriter().print(JsonMapper.obj2String(noAthuResult));
        } else if(servletUrl.endsWith(".page")){
            clientRedirect(noAuthRedirectUrl, response);
        }
    }

    /**
     * 跳转到无权限页面
     * @param url 无权限页面地址
     * @param response
     * @throws IOException
     */
    private void clientRedirect(String url, HttpServletResponse response) throws IOException{
        response.setHeader("Context-Type", "text/html");
        response.getWriter().print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"/>\n"
                + "<title>跳转中...</title>\n" + "</head>\n" + "<body>\n" + "跳转中，请稍候...\n" + "<script type=\"text/javascript\">//<![CDATA[\n"
                + "window.location.href='" + url + "?ret='+encodeURIComponent(window.location.href);\n" + "//]]></script>\n" + "</body>\n" + "</html>\n");

    }

    @Override
    public void destroy() {

    }
}
